﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace LightController
{
    /// <summary>
    /// ch:0-16,0 代表所有通道，1-16 代表对应通道的通道序号
    /// val:0-255
    /// </summary>
    [Serializable]
    public class OPTController : ILightController
    {
        [NonSerialized]
        private OPTControllerAPI controller = new OPTControllerAPI();
        public string Name { get; set; } = "OPTController";
        public string CommunicationAddress { get; set; }
        public int ChanelCount { get; set; } = 16;
        public bool IsConnect
        {
            get
            {
                if (controller == null || controller.IsConnect() != 0)
                {
                    return false;
                }
                return true;
            }
        }
        [NonSerialized]
        private static readonly object _lock = new object();
        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;
        [NonSerialized]
        private string status = string.Empty;
        public string Status
        {
            get
            {
                return status;
            }
            private set
            {
                status = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value.ToString()));
            }
        }

        public List<LightChanel> ChanelList { get; set; } = new List<LightChanel>();

        private string id = string.Empty;
        public string ID
        {
            get
            {
                return id;
            }

            set
            {
                id = value;
            }
        }

        public bool Connect()
        {
            int ret = 0;
            if (controller == null)
            {
                controller = new OPTControllerAPI();
            }
            try
            {
                if (IsConnect == true)
                {
                    Status = $"{Name} Controller:{CommunicationAddress} is Already Connected!";
                    return true;
                }
                Status = $"Connecting OPT Controller:{CommunicationAddress}";
                if (CommunicationAddress.Contains("."))//IP
                {
                    ret = controller.CreateEthernetConnectionByIP(CommunicationAddress);
                }
                else
                {
                    ret = controller.InitSerialPort(CommunicationAddress);
                }
                if (ret == 0)
                {
                    Status = $"Connected OPT Controller:{CommunicationAddress} Success！";
                    return true;
                }
                else
                {
                    Status = $"Connect OPT Controller：{CommunicationAddress} Fail！retCode：{ret}";
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"OPTController:{CommunicationAddress} Connect failed,Exception：{ex.Message + ex.StackTrace}");
            }

        }

        public bool Disconnect()
        {
            int ret = 0;
            try
            {
                Status = $"Disconnect OPT Controller:{CommunicationAddress}";
                if (CommunicationAddress.Contains("."))//IP
                {
                    ret = controller.DestroyEthernetConnect();
                }
                else
                {
                    ret = controller.ReleaseSerialPort();
                }
                if (ret == 0)
                {
                    Status = $"Disconnect OPT Controller:{CommunicationAddress} Success！";
                    return true;
                }
                else
                {
                    Status = $"Disconnect OPT Controller：{CommunicationAddress} Fail！retCode：{ret}";
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"OPTController:{CommunicationAddress} Disconnect failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }

        public bool SetIntensity(int ch, int val)
        {
            int ret = 0;
            try
            {
                Status = $"SetIntensity OPT Controller:{CommunicationAddress} ,CH：{ch},Value{val}！";
                ret = controller.SetIntensity(ch, val);
                if (ret == 0)
                {
                    Status = $"SetIntensity OPT Controller:{CommunicationAddress} Success,，CH:{ch}，Value:{val}！";
                    return true;
                }
                else
                {
                    Status = $"SetIntensity OPT Controller：{CommunicationAddress} Fail！retCode：{ret},CH:{ch},Value:{val}！";
                    return false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                throw new Exception($"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }

        public bool ReadIntensity(int ch,ref int val)
        {
            int ret = 0;
            try
            {
                Status = $"ReadIntensity OPT Controller:{CommunicationAddress} ,CH：{ch}！";
                ret = controller.ReadIntensity(ch,ref val);
                if (ret == 0)
                {
                    Status = $"ReadIntensity OPT Controller:{CommunicationAddress} Success,，CH:{ch}，Value:{val}！";
                    return true;
                }
                else
                {
                    Status = $"ReadIntensity OPT Controller：{CommunicationAddress} Fail！retCode：{ret},CH:{ch},Value:{val}！";
                    return false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                throw new Exception($"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }
        
        public bool SetMultiIntensity(List<int> chs, List<int> vals)
        {
            int ret = 0;

            if (chs.Count != vals.Count)
            {
                throw new Exception($"OPTController:{CommunicationAddress},Channel's Count is Not Equal Value's Count!");
            }

            List<OPTControllerAPI.IntensityItem> IntensityItemList = new List<OPTControllerAPI.IntensityItem>();
            for (int j = 1; j < 5; j++)
            {
                bool bb = false;
                for (int i = 0; i < chs.Count; i++)
                {
                    if (j== chs[i])
                    {
                        bb = true;
                        IntensityItemList.Add(new OPTControllerAPI.IntensityItem() { channel = chs[i], intensity = vals[i] });
                    }
           
                }
                if (!bb)
                    IntensityItemList.Add(new OPTControllerAPI.IntensityItem() { channel = j, intensity = 0 });
            }
           
            try
            {

                Status = $"SetMultiIntensity OPT Controller:{CommunicationAddress},CH:{string.Join(",", chs)}，Value:{string.Join(",", vals)}！";
                ret = controller.SetMultiIntensity(IntensityItemList.ToArray(), IntensityItemList.Count);
                if (ret == 0)
                {
                    Status = $"SetMultiIntensity OPT Controller:{CommunicationAddress} Success,，CH:{string.Join(",", chs)}，Value:{string.Join(",", vals)}！";
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetMultiIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                throw new Exception($"OPTController:{CommunicationAddress} SetMultiIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }

        public bool SetMultiIntensity(List<int> chs, List<int> vals, string ProdcutAdress, string ProdcutName, int openCount)
        {
            int ret = 0;

            if (chs.Count != vals.Count)
            {
                throw new Exception($"OPTController:{CommunicationAddress},Channel's Count is Not Equal Value's Count!");
            }

            List<OPTControllerAPI.IntensityItem> IntensityItemList = new List<OPTControllerAPI.IntensityItem>();
            for (int j = 1; j < 5; j++)
            {
                bool bb = false;
                for (int i = 0; i < chs.Count; i++)
                {
                    if (j == chs[i])
                    {
                        bb = true;
                        IntensityItemList.Add(new OPTControllerAPI.IntensityItem() { channel = chs[i], intensity = vals[i] });
                    }

                }
                if (!bb)
                    IntensityItemList.Add(new OPTControllerAPI.IntensityItem() { channel = j, intensity = 0 });
            }

            try
            {

                Status = $"SetMultiIntensity OPT Controller:{CommunicationAddress},CH:{string.Join(",", chs)}，Value:{string.Join(",", vals)}！";
                ret = controller.SetMultiIntensity(IntensityItemList.ToArray(), IntensityItemList.Count);
                if (ret == 0)
                {
                    Status = $"SetMultiIntensity OPT Controller:{CommunicationAddress} Success,，CH:{string.Join(",", chs)}，Value:{string.Join(",", vals)}！";
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetMultiIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                throw new Exception($"OPTController:{CommunicationAddress} SetMultiIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }
        /// <summary>
        /// 全关
        /// </summary>
        public bool CloseAllLight()
        {
            bool result = true;
            try
            {
                int ret = controller.SetIntensity(0, 0);
                if (ret == 0)
                {
                    Status = $"SetIntensity Success OPT Controller:{CommunicationAddress} ,CH:{0},Value:{0}！retCode:{ret}";
                }
                else
                {
                    Status = $"SetIntensity Fail OPT Controller:{CommunicationAddress} ,CH:{0},Value:{0}！retCode:{ret}";
                    result = false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                result = false;
                throw new Exception($"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
            return result;
        }
        /// <summary>
        /// 全开
        /// </summary>
        public bool OpenAllLight()
        {
            bool result = true;
            try
            {
                int ret = controller.SetIntensity(0, 255);
                if (ret == 0)
                {
                    Status = $"SetIntensity Success OPT Controller:{CommunicationAddress} ,CH:{0},Value:{255}！retCode:{ret}";
                }
                else
                {
                    Status = $"SetIntensity Fail OPT Controller:{CommunicationAddress} ,CH:{0},Value:{255}！retCode:{ret}";
                    result = false;
                }
            }
            catch (Exception ex)
            {
                Status = $"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}";
                result = false;
                throw new Exception($"OPTController:{CommunicationAddress} SetIntensity failed,Exception：{ex.Message + ex.StackTrace}");
            }
            return result;
        }
    }
}
